<!--
 * @Author: 安绍龙
 * @Date: 2024年11月29日
 * @LastEditTime: 2024年11月29日
 * @LastEditors: 安绍龙
 * @Description: svg图标使用组件，传对应文件名，即可使用，文件必须为svg，且存放到对应目录下
 * FilePath: \src\components\MIcon.vue
 -->
<template>
  <i :style="style" class="inline-block box-border" />
</template>

<script setup>
const props = defineProps({
  name: {
    type: String,
    required: true
  }
})
const style = ref({})

onMounted(async () => {
  await updateIcon()
})

watch(
  () => props.name,
  async () => {
    await updateIcon()
  }
)

async function updateIcon() {
  // 根据名称获取到svg文件内容，raw模式可以获取文本内容
  const module = await import(`@/assets/icons/${props.name}.svg?raw`)
  style.value = svgToCss(module.default)
}
/**
 * @param svg svg字符串
 * @returns svg 转义后的svg字符串
 * @description 处理svg文件，避免存在换行，或者符号问题
 */
function encodeSvg(svg) {
  return svg.replace('<svg', (~svg.indexOf('xmlns') ? '<svg' : '<svg xmlns="http://www.w3.org/2000/svg"'))
    .replace(/"/g, '\'')
    .replace(/%/g, '%25')
    .replace(/#/g, '%23')
    .replace(/\{/g, '%7B')
    .replace(/\}/g, '%7D')
    .replace(/</g, '%3C')
    .replace(/>/g, '%3E')
    .replace(/[\r\n\t]/g, '')
}

/**
 * @param svg svg字符串
 * @returns css样式
 * @description 将svg转换为css样式
 */
function svgToCss(svg) {
  // console.log('svgToCss', encodeSvg(svg))
  const mode = svg.includes('currentColor') ? 'mask' : 'background-img'
  const uri = `url("data:image/svg+xml;utf8,${encodeSvg(svg)}")`
  if (mode === 'mask') {
    // 单色图标，颜色随文字颜色变化
    return {
      'mask': `${uri} no-repeat`,
      'mask-size': '100% 100%',
      'background-color': 'currentColor',
      'height': '1em',
      'width': '1em'
    }
  } else {
    // 彩色图标。不改变颜色
    return {
      'background': `${uri} no-repeat`,
      'background-size': '100% 100%',
      'background-color': 'transparent',
      'height': '1em',
      'width': '1em'
    }
  }
}
</script>

<style scoped></style>
